package net.jueb.protoServer.portService;
import io.netty.channel.Channel;
import java.util.concurrent.ConcurrentHashMap;
import net.jueb.protoServer.controller.ServiceController;
import net.jueb.protoServer.protocol.PortProtocol;

/**
 * 端口服务
 * @author Administrator
 * @param <R> 接受消息类型
 */
public abstract class PortService<R> implements PortServiceLifeCyle{
	/**
	 * 端口类型
	 * @author Administrator
	 *
	 */
	public static enum PortType
	{
		TCP,UDP;
	}
	
	protected final int port;
	protected final String portServiceName;
	private Channel channel;
	private PortProtocol<R> portProtocol;

	/**
	 * 该服务使用的消息处理控制器
	 */
	private final ConcurrentHashMap<Integer,ServiceController<?>> controllers;
	
	public PortService(int port, String portServiceName,PortProtocol<R> portProtocol) {
		super();
		this.port = port;
		this.portServiceName = portServiceName;
		this.portProtocol=portProtocol;
		this.controllers=portProtocol.getServiceControllers();
	}
	
	/**
	 * 获取传输协议
	 * @return
	 */
	public final PortProtocol<R> getPortProtocol() {
		return portProtocol;
	}


	/**
	 * 设置传输协议可用来动态调整消息
	 * @param portProtocol
	 */
	public final void setPortProtocol(PortProtocol<R> portProtocol) {
		this.portProtocol = portProtocol;
	}



	public final int getPort() {
		return port;
	}
	public final String getPortServiceName() {
		return portServiceName;
	}
	/**
	 * 绑定的netty端口通道
	 * 如果管道为null也会绑定为null
	 * @param channel
	 */
	public final void bindChannel(Channel channel)
	{
		this.channel=channel;
	}
	/**
	 * 取消通道绑定
	 * @param channle
	 */
	public final void unBindChannel()
	{
		this.channel=null;
	}
	/**
	 * 获取绑定的通道
	 * @return
	 */
	public final Channel getBindChannel()
	{
		return this.channel;
	}
	
	/**
	 * 根据子类实现获取该端口服务用到的控制器集合,类型为<消息ID,消息ID对应的控制器>
	 * @return
	 */
	public final ConcurrentHashMap<Integer,ServiceController<?>> getControllers()
	{
		return this.controllers;
	}

	/**
	 * 添加控制器,以控制器的MessageId为key
	 * 当消息ID相同时将会被替换
	 * @param controller
	 */
	public final void addController(ServiceController<?> controller)
	{
		this.controllers.put(controller.getId(),controller);
	}
	
	/**
	 * 删除控制器
	 * @param messageId 控制器关联的消息ID
	 * @return 返回被移出的控制器
	 */
	public final ServiceController<?> removeController(int messageId)
	{
		return this.controllers.remove(messageId);
	}
	
	public abstract PortType getPortType();

	/**
	 * 根据绑定的端口管道状态确定是否运行。
	 * @return
	 */
	public abstract boolean isRunning();
	
}
